package tum0r.json;

import java.util.*;

/**
 * 工程: XJSON<br>
 * 包: tum0r.json<br>
 * 创建者: tum0r<br>
 * 创建时间: 2020/9/15 17:17<br>
 * <br>
 */
class JSON {
    protected JSONNode rootNode;
    private int count;
    private final Set<String> keySet;

    protected JSON() {
        rootNode = new JSONNode();
        count = 0;
        keySet = new TreeSet<>();
    }

    public int count() {
        return count;
    }

    protected boolean addCount() {
        boolean result = false;
        if (count + 1 < Integer.MAX_VALUE) {
            count++;
            result = true;
        }
        return result;
    }

    private void addHeight(JSONNode node) {
        if (node != null) {
            JSONNode temp = node;
            while (temp.rootNode != null) {
                boolean flag = true;
                if (temp.rootNode.leftNode == temp) {
                    temp.rootNode.leftHeight++;
                    flag = temp.rootNode.rightHeight >= temp.rootNode.leftHeight;
                } else if (temp.rootNode.rightNode == temp) {
                    temp.rootNode.rightHeight++;
                    flag = temp.rootNode.leftHeight >= temp.rootNode.rightHeight;
                }
                if (flag) {
                    break;
                }
                temp = temp.rootNode;
            }
        }
    }

    protected boolean put(String key, Object value) {
        if (key == null || key.equals("")) {
            key = count() + "";
        }
        boolean result = addCount();
        if (result) {
            JSONNode tempNode = rootNode;
            while (tempNode.key != null) {
                if (key.compareTo(tempNode.key) > 0) {
                    if (tempNode.rightNode == null) {
                        tempNode.rightNode = new JSONNode();
                        tempNode.rightNode.rootNode = tempNode;
                        addHeight(tempNode.rightNode);
                    }
                    tempNode = tempNode.rightNode;
                } else if (key.compareTo(tempNode.key) < 0) {
                    if (tempNode.leftNode == null) {
                        tempNode.leftNode = new JSONNode();
                        tempNode.leftNode.rootNode = tempNode;
                        addHeight(tempNode.leftNode);
                    }
                    tempNode = tempNode.leftNode;
                } else {
                    break;
                }
            }
            tempNode.key = key;
            tempNode.value = value;
            keySet.add(key);

        }
        return result;
    }

    public long put(JSON json) {
        long result = 0;
        if (json != null) {
            if (this instanceof JSONObject) {
                if (json instanceof JSONObject) {
                    for (String key : json.keySet) {
                        result += this.put(key, ((JSONObject) json).getObject(key)) ? 1 : 0;
                    }
                } else if (json instanceof JSONArray) {
                    for (int i = 0; i < json.count(); i++) {
                        result += this.put(null, ((JSONArray) json).getObject(i)) ? 1 : 0;
                    }
                }
            } else if (this instanceof JSONArray) {
                if (json instanceof JSONObject) {
                    for (String key : json.keySet) {
                        result += ((JSONArray) this).add(((JSONObject) json).getObject(key)) ? 1 : 0;
                    }
                } else if (json instanceof JSONArray) {
                    for (int i = 0; i < json.count(); i++) {
                        result += ((JSONArray) this).add(((JSONArray) json).getObject(i)) ? 1 : 0;
                    }
                }
            }
        }
        return result;
    }

    public JSON clone() {
        JSON result = new JSON();
        result.put(this);
        return result;
    }

    public boolean remove(String key) {
        boolean result = false;
        JSONNode node = getJsonNode(key);
        if (node != null) {

        }
        return result;
    }

    protected JSONNode getJsonNode(String key) {
        JSONNode result = null;
        if (key != null && !key.equals("")) {
            result = rootNode;
            while (result != null) {
                if (key.compareTo(result.key) > 0) {
                    result = result.rightNode;
                } else if (key.compareTo(result.key) < 0) {
                    result = result.leftNode;
                } else {
                    break;
                }
            }
        }
        return result;
    }

    public boolean containsKey(String key) {
        JSONNode tempNode = getJsonNode(key);
        return tempNode != null && tempNode.key.equals(key);
    }

    public Set<String> getKeySet() {
        return keySet;
    }

    protected static Object parseValue(String value) {
        Object result = (value == null || value.equals("") || value.equals("null")) ? null : value.trim();
        if (result != null) {
            if (value.equals("true") | value.equals("false")) {
                result = Boolean.parseBoolean(value);
            } else {
                try {
                    result = Integer.parseInt(value);
                } catch (Exception ignored) {
                    try {
                        result = Long.parseLong(value);
                    } catch (Exception ignored2) {
                        result = ((String) result).replace("\"", "");
                    }
                }
            }
        }
        return result;
    }

    public Object[] toArray() {
        return toArray(new Object[0]);
    }

    public Object[] toArray(int start) {
        return toArray(new Object[0], start);
    }

    public Object[] toArray(int start, int end) {
        return toArray(new Object[0], start, end);
    }

    private <T> T[] toArray(T[] array) {
        return toArray(array, 0, count());
    }

    private <T> T[] toArray(T[] array, int start) {
        return toArray(array, start, count());
    }

    @SuppressWarnings("unchecked")
    private <T> T[] toArray(T[] array, int start, int end) {
        T[] result = null;
        if (array != null) {
            int size = Math.max(end - start, 0);
            result = (T[]) java.lang.reflect.Array.newInstance(array.getClass().getComponentType(), size);
            if (size > 0) {
                Object[] temp = result;
                int index = 0;
                Iterator<String> iterator = getKeySet().iterator();
                String key;
                while (iterator.hasNext()) {
                    key = iterator.next();
                    temp[index++] = getJsonNode(key).getObject();
                }
            }
        }
        return result;
    }

}
